package com.elong.businesstravel.base.recorder;

import java.io.File;
import java.io.IOException;

import com.elong.businesstravel.base.uploadpic.UploadPic;
import com.tencent.tauth.UploadFileToWeiyun;

import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;

public class Recorder implements OnCompletionListener, OnErrorListener {
	static final String SAMPLE_PREFIX = "recording";
	static final String SAMPLE_PATH_KEY = "sample_path";
	static final String SAMPLE_LENGTH_KEY = "sample_length";
	
	public static final int RECORD_LENGHT_DEFAULT = 60;
	
	public static final String RECORD = "recorder";

	public static final int IDLE_STATE = 0;
	public static final int RECORDING_STATE = 1;
	public static final int PLAYING_STATE = 2;

	int mState = IDLE_STATE;

	public static final int NO_ERROR = 0;
	public static final int SDCARD_ACCESS_ERROR = 1;
	public static final int INTERNAL_ERROR = 2;
	public static final int IN_CALL_RECORD_ERROR = 3;

	public interface OnStateChangedListener {
		public void onStateChanged(int state);

		public void onError(int error);

		public void onCompletion();
	}

	OnStateChangedListener mOnStateChangedListener = null;

	long mSampleStart = 0; // time at which latest record or play operation
							// started
	int mSampleLength = 0; // length of current sample
	File mSampleFile = null;

	MediaRecorder mRecorder = null;
	MediaPlayer mPlayer = null;
	
	private int mRecordLenght = RECORD_LENGHT_DEFAULT;
	
	public void setRecordLenght(int recordLenght) {
		if(recordLenght <= 10){
			throw new RuntimeException("recordLenght > 10");
		}
		mRecordLenght = recordLenght;
	}
	
	public int getRecordLenght(){
		return mRecordLenght;
	}

	public Recorder() {
	}

	public void saveState(Bundle recorderState) {
		recorderState.putString(SAMPLE_PATH_KEY, mSampleFile.getAbsolutePath());
		recorderState.putInt(SAMPLE_LENGTH_KEY, mSampleLength);
	}

	public int getMaxAmplitude() {
		if (mState != RECORDING_STATE)
			return 0;
		return mRecorder.getMaxAmplitude();
	}

	public void restoreState(Bundle recorderState) {
		String samplePath = recorderState.getString(SAMPLE_PATH_KEY);
		if (samplePath == null)
			return;
		int sampleLength = recorderState.getInt(SAMPLE_LENGTH_KEY, -1);
		if (sampleLength == -1)
			return;

		File file = new File(samplePath);
		if (!file.exists())
			return;
		if (mSampleFile != null
				&& mSampleFile.getAbsolutePath().compareTo(
						file.getAbsolutePath()) == 0)
			return;

		delete();
		mSampleFile = file;
		mSampleLength = sampleLength;

		signalStateChanged(IDLE_STATE);
	}

	public void setOnStateChangedListener(OnStateChangedListener listener) {
		mOnStateChangedListener = listener;
	}

	public int state() {
		return mState;
	}

	public int progress() {
		if (mState == RECORDING_STATE || mState == PLAYING_STATE)
			return (int) ((System.currentTimeMillis() - mSampleStart) / 1000);
		return 0;
	}

	public int sampleLength() {
		return mSampleLength;
	}

	public File sampleFile() {
		return mSampleFile;
	}

	/**
	 * Resets the recorder state. If a sample was recorded, the file is deleted.
	 */
	public void delete() {
		stop();

		if (mSampleFile != null)
			mSampleFile.delete();

		mSampleFile = null;
		mSampleLength = 0;

		signalStateChanged(IDLE_STATE);
	}

	/**
	 * Resets the recorder state. If a sample was recorded, the file is left on
	 * disk and will be reused for a new recording.
	 */
	public void clear() {
		stop();

		mSampleLength = 0;

		signalStateChanged(IDLE_STATE);
	}

	public void startRecording(int outputfileformat, String extension,
			Context context) {
		stop();

		File sampleDir = Environment.getExternalStorageDirectory();
		if (!sampleDir.canWrite()) // Workaround for broken sdcard support on
									// the device.
			sampleDir = new File("/sdcard/sdcard");

		File dirFile = new File(sampleDir.getAbsolutePath() + "/" + UploadPic.CLT + "/" + RECORD);
		if (!dirFile.exists())
			dirFile.mkdirs();

		try {
			mSampleFile = File
					.createTempFile(SAMPLE_PREFIX, extension, dirFile);
		} catch (IOException e) {
			setError(SDCARD_ACCESS_ERROR);
			return;
		}

		mRecorder = new MediaRecorder();
		mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
		mRecorder.setOutputFormat(outputfileformat);
		mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
		mRecorder.setOutputFile(mSampleFile.getAbsolutePath());

		// Handle IOException
		try {
			mRecorder.prepare();
		} catch (IOException exception) {
			setError(INTERNAL_ERROR);
			mRecorder.reset();
			mRecorder.release();
			mRecorder = null;
			return;
		}
		// Handle RuntimeException if the recording couldn't start
		try {
			mRecorder.start();
		} catch (RuntimeException exception) {
			AudioManager audioMngr = (AudioManager) context
					.getSystemService(Context.AUDIO_SERVICE);
			boolean isInCall = audioMngr.getMode() == AudioManager.MODE_IN_CALL;
			if (isInCall) {
				setError(IN_CALL_RECORD_ERROR);
			} else {
				setError(INTERNAL_ERROR);
			}
			mRecorder.reset();
			mRecorder.release();
			mRecorder = null;
			return;
		}
		mSampleStart = System.currentTimeMillis();
		setState(RECORDING_STATE);
	}

	public void stopRecording() {
		if (mRecorder == null)
			return;

		mRecorder.stop();
		mRecorder.release();
		mRecorder = null;

		mSampleLength = (int) ((System.currentTimeMillis() - mSampleStart) / 1000);
		setState(IDLE_STATE);
	}

	public void startPlayback() {
		stop();

		mPlayer = new MediaPlayer();
		try {
			mPlayer.setDataSource(mSampleFile.getAbsolutePath());

			mPlayer.setOnCompletionListener(this);
			mPlayer.setOnErrorListener(this);
			mPlayer.prepare();
			mPlayer.start();
		} catch (IllegalArgumentException e) {
			setError(INTERNAL_ERROR);
			mPlayer = null;
			return;
		} catch (IOException e) {
			setError(SDCARD_ACCESS_ERROR);
			mPlayer = null;
			return;
		}

		mSampleStart = System.currentTimeMillis();
		setState(PLAYING_STATE);
	}

	public void startPlayback(String file) {
		stop();

		mPlayer = new MediaPlayer();
		try {
			mPlayer.setDataSource(file);

			mPlayer.setOnCompletionListener(this);
			mPlayer.setOnErrorListener(this);
			mPlayer.prepare();
			mPlayer.start();
		} catch (IllegalArgumentException e) {
			setError(INTERNAL_ERROR);
			mPlayer = null;
			return;
		} catch (IOException e) {
			setError(SDCARD_ACCESS_ERROR);
			mPlayer = null;
			return;
		}

		mSampleStart = System.currentTimeMillis();
		setState(PLAYING_STATE);
	}

	public void stopPlayback() {
		if (mPlayer == null) // we were not in playback
			return;

		mPlayer.stop();
		mPlayer.release();
		mPlayer = null;
		setState(IDLE_STATE);
	}

	public void stop() {
		stopRecording();
		stopPlayback();
	}

	public boolean onError(MediaPlayer mp, int what, int extra) {
		stop();
		setError(SDCARD_ACCESS_ERROR);
		return true;
	}

	public void onCompletion(MediaPlayer mp) {
		stop();

		if (mOnStateChangedListener != null)
			mOnStateChangedListener.onCompletion();
	}

	private void setState(int state) {
		if (state == mState)
			return;

		mState = state;
		signalStateChanged(mState);
	}

	private void signalStateChanged(int state) {
		if (mOnStateChangedListener != null)
			mOnStateChangedListener.onStateChanged(state);
	}

	private void setError(int error) {
		if (mOnStateChangedListener != null)
			mOnStateChangedListener.onError(error);
	}

	public String getRecorderFile() {

		if (mSampleFile != null)
			return mSampleFile.getAbsolutePath();
		else
			return null;
	}
}
